-
Notifications
You must be signed in to change notification settings - Fork 2.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Resolves offline sound playback by caching assets locally #50130
Resolves offline sound playback by caching assets locally #50130
Conversation
@rayane-djouah Please copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button] |
Reviewer Checklist
Screenshots/VideosAndroid: Nativeandroid_native.mp4Android: mWeb Chromeandroid_mweb_chrome.mp4iOS: NativeSimulator.Screen.Recording.-.iPhone.15.Pro.Max.-.2024-10-18.at.22.59.17.mp4iOS: mWeb SafariSimulator.Screen.Recording.-.iPhone.15.Pro.Max.-.2024-10-18.at.22.47.53.mp4MacOS: Chrome / SafariScreen.Recording.2024-10-18.at.9.03.44.PM.movMacOS: DesktopScreen.Recording.2024-10-18.at.9.07.20.PM.mov |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good! left some comments
// Cache each sound file if it's not already cached. | ||
const cachePromises = soundFiles.map((soundFile) => { | ||
return cache.match(soundFile).then((response) => { | ||
if (response) { | ||
return; | ||
} | ||
return cache.add(soundFile); | ||
}); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Potential Issue: Stale Cache Entries
Clients may continue using outdated cached sound files if the server updates them. To ensure users always have the latest sounds, we should refresh the cache on every app load.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@rayane-djouah Not sure about this suggestion, but is it better to use in-memory cache if we want to update the sound assets on each page load?
Replacing the cache during the page load would result in fetching assets from the remote URL every time we load.
I think server will rarely update sound assets. To optimize, how about clearing sound assets during logout and resetting the app on the troubleshooting page?
src/libs/Sound/index.ts
function clearSoundAssetsCache() {
// Exit early if the Cache API is not available in the current browser.
if (!('caches' in window)) {
return;
}
caches.delete('sound-assets').then((success) => {
if (success) {
console.log('Sound assets cache cleared.');
} else {
console.log('Failed to clear sound assets cache.');
}
}).catch((error) => {
console.error('Error clearing sound assets cache:', error);
});
}
And execute that function in:
src/libs/actions/App.ts
function clearOnyxAndResetApp(shouldNavigateToHomepage?: boolean) {
......
clearSoundAssetsCache();
.....
And for clear action in Troubleshoot page:
src/libs/actions/App.ts
function clearOnyxAndResetApp(shouldNavigateToHomepage?: boolean) {
.........
clearSoundAssetsCache();
}
Kapture.2024-10-04.at.08.01.29.mp4
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@wildan-m, I agree that clearing the cache upon logout and during troubleshooting is a smart approach to handle updates to sound assets.
To complement this, we could consider a versioned cache strategy. This involves appending a version number to the cache name. We can update the cache version whenever we change or add a sound.
// Update this version string when new sound files are added or existing ones are changed to invalidate old caches and prompt caching of the new assets.
const CURRENT_CACHE_VERSION = 'sound-assets-v1';
caches.open(CURRENT_CACHE_VERSION).then(...)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@rayane-djouah how would we determine version? usually server will send the version to invalidate the cache. Is there any API for that purpose?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another common approach is version the file name sound-v1.mp3, since the name already stored as key to put the cache I think we don't need any other change to version the cache in FE
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The updated main has been merged and clearSoundAssetsCache has been implemented
…x/47148-fix-sound-offline
Co-authored-by: rayane-djouah <77965000+rayane-djouah@users.noreply.github.com>
Co-authored-by: rayane-djouah <77965000+rayane-djouah@users.noreply.github.com>
…x/47148-fix-sound-offline
@@ -559,6 +560,7 @@ function clearOnyxAndResetApp(shouldNavigateToHomepage?: boolean) { | |||
}); | |||
}); | |||
}); | |||
clearSoundAssetsCache(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will not it crash mobile app? It looks like clearSoundAssetsCache
is implemented only on web and such function doesn't exist on mobile? Correct me if I'm wrong 🙏
Also, why do we need to clear a cache on logout? In case if we want to replace sound we can just change name and we'll simply download new version of the file? Don't you think that clearSoundAssetsCache
is kind of over engineering?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will not it crash mobile app?
I think it won't crash, there is check if (!('caches' in window)) {
and also try catch, but let me know if we need to extract the function and create platform specific code
function clearSoundAssetsCache() {
// Exit early if the Cache API is not available in the current browser.
if (!('caches' in window)) {
return;
}
caches
.delete('sound-assets')
.then((success) => {
if (success) {
return;
}
Log.alert('[sound] Failed to clear sound assets cache.');
})
.catch((error) => {
Log.alert('[sound] Error clearing sound assets cache:', {message: (error as Error).message});
});
Also, why do we need to clear a cache on logout?
The assets might be replaced without changing the name.
we can just change name and we'll simply download new version of the file?
replacing the name might need code change to the assets references and we might need to rebuild the app each time we change the name
Don't you think that clearSoundAssetsCache is kind of over engineering?
I don't think so, the code is quiet simple and it's also make sense to make it as part of app reset
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it won't crash, there is check if (!('caches' in window)) {
I think clearSoundAssetsCache
will be undefined and you will receive undefined is not a function
. Did you test native code in this PR?
The assets might be replaced without changing the name.
At the moment only developer can update asset. So if they update it without changing a name it'll be kind of developer fault...
replacing the name might need code change to the assets references and we might need to rebuild the app each time we change the name
We can replace only name of SOUNDS
, i. e.:
const SOUNDS = {
DONE: 'done-v1',
SUCCESS: 'success',
ATTENTION: 'attention',
RECEIVE: 'receive',
} as const;
And other code will be untouched 🤷♂️
I don't think so, the code is quiet simple and it's also make sense to make it as part of app reset
Oki doki, just wanted to be sure, that alternative solution also has been considered 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think clearSoundAssetsCache will be undefined and you will receive undefined is not a function.
@kirillzyusko you are right, I've updated the native implementation to empty function. thank you!
Testing the PR today |
@wildan-m |
@rayane-djouah I think that's expected, it should be reloaded whole online for at least once to fill up the cache again. Or should we directly call |
@wildan-m I think it's fine to keep the current behaviour 👍 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM and tests well 🚀
@yuwenmemon all yours! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
@yuwenmemon looks like this was merged without a test passing. Please add a note explaining why this was done and remove the |
✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release. |
False positive, check the latest build -tests were passing. |
🚀 Deployed to staging by https://github.com/yuwenmemon in version: 9.0.52-0 🚀
|
🚀 Deployed to production by https://github.com/yuwenmemon in version: 9.0.52-5 🚀
|
Details
This PR resolves offline sound playback by caching assets locally for web and desktop environments.
Fixed Issues
$ #47148
PROPOSAL: #47148 (comment) (Alternative 4)
Tests
Offline tests
Same as test
QA Steps
Same as test
PR Author Checklist
### Fixed Issues
section aboveTests
sectionOffline steps
sectionQA steps
sectiontoggleReport
and notonIconClick
)myBool && <MyComponent />
.src/languages/*
files and using the translation methodSTYLE.md
) were followedAvatar
, I verified the components usingAvatar
are working as expected)StyleUtils.getBackgroundAndBorderStyle(theme.componentBG)
)Avatar
is modified, I verified thatAvatar
is working as expected in all cases)Design
label and/or tagged@Expensify/design
so the design team can review the changes.ScrollView
component to make it scrollable when more elements are added to the page.main
branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTest
steps.Screenshots/Videos
Android: Native
Kapture.2024-10-03.at.13.22.01.mp4
Android: mWeb Chrome
Kapture.2024-10-03.at.13.29.35.mp4
iOS: Native
Kapture.2024-10-03.at.11.30.24.mp4
iOS: mWeb Safari
Kapture.2024-10-03.at.11.37.01.mp4
MacOS: Chrome / Safari
Kapture.2024-10-03.at.11.40.45.mp4
MacOS: Desktop
Kapture.2024-10-03.at.13.25.40.mp4